
import time

import yaml
from appium import webdriver
from appium.webdriver import WebElement
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.common.touch_action import TouchAction
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.support import expected_conditions as EC, expected_conditions
from selenium.webdriver.support.wait import WebDriverWait




class BasePage():
    black_list = [('xpath', '//*[@text="跳过"]'), ('id', 'backImg')]
    max_num = 3
    error_num = 0
    index = ('xpath', '//*[@text="首页"]')

    def __init__(self, driver: WebDriver = None):
        """
        初始化应用
        """
        if driver is None:
            caps = {}
            caps['platformVersion'] = '7.1.2'
            caps['platformName'] = 'Android'  # 打开什么平台的app，固定的 > 启动安卓平台
            caps['appPackage'] = 'com.znb.zxx'  # app的名字：adb shell dumpsys package XXX
            # caps['appPackage'] = 'com.taobao.idlefish'  # app的名字：adb shell dumpsys package XXX
            caps['deviceName'] = 'HUAWEI P20'
            # caps['appActivity'] = 'com.taobao.fleamarket.home.activity.MainActivity'  # 同上↑  # .pages.splash.SplashActivity   pages.main.MainActivity
            caps['appActivity'] = 'com.work.demo.main.MainActivity'
            caps['unicodeKeyboard'] = True
            # caps['autoLaunch'] = False  # =False直接使用打开的app进行测试
            caps['noReset'] = True
            self.driver = webdriver.Remote('http://localhost:4723/wd/hub', caps)
            self.driver.implicitly_wait(5)
        else:
            self.driver = driver

    def find(self, locator):
        result: WebElement = WebDriverWait(self.driver, timeout=10).until(EC.element_to_be_clickable(locator))
        return result

    def open_yaml_element(self, file, key_name):
        # 读取yaml，取出关键数据，用parse解析
        with open(file, encoding="utf-8") as f:
            data = yaml.load(f)
            self.parse(data[key_name])

    def parse(self, func):
        # 遍历每一个步骤
        for ele in func:
            # 如果操作是click就去点击
            if "click" == ele["action"]:  # 当action是click的时候
                self.find(ele["by"], ele["locator"]).click()  # 去查找他的元素并且点击
            elif "send" == ele["action"]:
                self.find(ele["by"], ele["locator"]).send_keys(ele["content"])

    def find_element(self, locator):
        """
            名字：动态查找元素
            参数：
                driver: 浏览器的实例化对象
                locator: 元素定位的方法 ("id", "username") / ("xpath", "xxxxx") /("aid", "xxxxx") /("aui", "xxxxx")
                    类型：
                        ID = "id"
                        XPATH = "xpath"
                        accessibility_id = "aid"
                        android_uiautomator = "aui"
                timeout: 超时时间：默认10
        """
        if locator[0] == "aid":
            locator = ("accessibility id", locator[1])
        if locator[0] == "text":
            locator = ("-android uiautomator", 'new UiSelector().text("{}")'.format(locator[1]))
        res: WebElement = WebDriverWait(self.driver, timeout=10).until(EC.element_to_be_clickable(locator))
        return res

    def click_element(self, driver, locator):
        self.find_element(driver, locator).click()

    def elements(self, locator):
        # 显示等待查找elments
        return WebDriverWait(self.driver, 10).until(EC.visibility_of_any_elements_located(locator))

    def get_toast_text(self, text_value):
        """
        获取toast
        :param driver:
        :return:
        """
        return self.driver.find_element_by_xpath("//*[contains(@text,{})]").format(text_value).text

    def find_by_scroll_and_swpie(self, locator):
        '''
        滚动查找元素的方法
        :param driver:需要传入的driver
        :param locator: text 文本值
                        resourceId
                        className
                        description ：content-desc定位方式 （类似文本值）
        '''
        return self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
                                        'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().{}("{}").instance(0));'.format(
                                            locator[0], locator[1]))

    def go_swipe(self, startx, endx, starty, endy):
        '''
            按照屏幕比例滑动
        '''
        size = self.driver.get_window_size()
        start_x = size["width"] * startx
        end_x = size["height"] * endx
        start_y = size["width"] * starty
        end_y = size["height"] * endy

        return self.driver.swipe(start_x, end_x, start_y, end_y)

    def back_activity(self, num):
        for i in range(num):
            time.sleep(1)
            self.driver.back()
            time.sleep(1)

    def is_element(self, locator):
        try:
            self.find_element(locator)
            return True
        except:
            return False

    def find_by_scroll(self, text_value):
        '''
        滚动查找元素的方法
        :param driver:需要传入的driver
        :param text_value:文本值
        :return:
        '''
        return self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
                                        'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("{}").instance(0));'.format(
                                            text_value))

    def judge_locator_visible(self, locator):
        '''
        判断元素是否可见，如果可见就返回这个元素
        :return:
        '''
        return WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable(locator))

    def driverTap(self, x, y, z=None):

        # 获取屏幕的 size
        size = self.driver.get_window_size()
        print(size)
        # 获取屏幕宽度 width
        width = size['width']
        # 获取屏幕高度 height
        height = size['height']
        # return self.driver.tap([((x / 1080) * width, (y / 2244) * height)], z)



    # 向左滑动。
    def swipLeft(self):
        l = self.getSize()
        x1 = int(l[0] * 0.5)
        y1 = int(l[1] * 0.5)
        x2 = int(l[0] * 0.5)
        self.driver.swipe(x1, y1, x2, y1)

    # 向右滑动。
    def swipRight(self):
        l = self.getSize()
        x1 = int(l[0] * 0.05)
        y1 = int(l[1] * 0.5)
        x2 = int(l[0] * 0.75)
        self.driver.swipe(x1, y1, x2, y1)

    # 屏幕向上滑动
    def swipeUp(self):
        l = self.getSize()
        x1 = int(l[0] * 0.5)  # x坐标
        y1 = int(l[1] * 0.75)  # 起始y坐标
        y2 = int(l[1] * 0.25)  # 终点y坐标
        self.driver.swipe(x1, y1, x1, y2)

    # 获得机器屏幕大小x,y
    def getSize(self):
        x = self.driver.get_window_size()['width']
        y = self.driver.get_window_size()['height']
        return (x, y)

    def swipeDown(self):
        # 屏幕向下滑动
        l = self.getSize()
        x1 = int(l[0] * 0.5)  # x坐标
        y1 = int(l[1] * 0.25)  # 起始y坐标
        y2 = int(l[1] * 0.75)  # 终点y坐标
        self.driver.swipe(x1, y1, x1, y2)

    def quit_app(self):
        self.driver.quit()

    def page(self, locator):
        '''
        返回至指定页面
        :return:
        '''

        try:
            self.driver.find_element(*locator)
        except:
            self.back_activity(1)
            return self.page(locator)

    def clickable_or_not(self, locator):
        '''
        判断元素是否可见 可点击
        :param by:
        :param locator:
        :return:
        '''

        result = WebDriverWait(self.driver, 5).until(expected_conditions.element_to_be_clickable(locator))
        return result

    def find_locator_and_back(self, locator, location, text_name, want_location, text_value=None):
        '''
        检查元素是否存在，不存在的话返回上一级
        :param locator: 首个定位器
        :param location: 希望找到的定位器
        :param text_name: 希望找到的定位器的文本值
        :param want_location: 希望找到的定位器
        text_value :或者希望找到的定位器的文本值
        :return:
        '''

        self.find(locator).click()
        try:
            if self.find(location).text == text_name or self.find(location).text == text_value:
                self.find(want_location).click()
                return True
            else:
                self.driver.back()
                self.find_locator_and_back(locator, location, text_name, want_location, text_value)
        except:
            self.driver.back()
            return print('没有找到元素')
            # self.find_locator_and_back(locator, location, text_name, want_location, text_value)

    def try_and_except(self):
        try:
            self.driver.keyevent('66')
        except:
            self.try_and_except()
